/**
 * @(#) RedPacketUtil.java    2015/08/13 16:24
 */
package com.banksoft.front.util;

import com.banksoft.admin.bean.PaySetting;
import com.banksoft.util.StringNumber;
import com.banksoft.util.UUIDFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.*;

/**
 * 类的功能，目的，描述等写在此处
 *
 * @author 张战军
 * @version 1.0
 */
public class RedPacketUtil {
    private static String send_redPacket_url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";

    //发送红包

    /**
     *
     * @param no   编号 类似订单编号
     * @param shName 商户名称 爱婴在线
     * @param openId 会员openId openId
     * @param money 发送金额
     * @param sentiment    祝福语
     * @param ip
     * @param eventName 活动名称
     * @param remark   备注信息
     * @return
     */
    public static Map sendRedPacket(String no, String shName, String openId, String money, String sentiment,
                                        String ip, String eventName, String remark, PaySetting paySetting) throws Exception {

        //组装数据
        Map<String, String> respMap = createRespMap(no, shName, openId, money, sentiment, ip, eventName, remark, paySetting);
        String respXml = createRespXml(respMap);
        String path = RedPacketUtil.class.getResource("/").getPath()+"apiclient_cert.p12";
        System.out.println("========== "+path);
       // String rootPath = ServletActionContext.getServletContext().getRealPath("/");
        Map<String, String> map = sendExecute(respXml, paySetting.getPayNo(), path);
        return dealWithBackData(map);
    }



    //组装数据
    private static Map<String, String> createRespMap(String no, String shName, String openId, String money, String sentiment,
            String ip, String eventName, String remark, PaySetting paySetting) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("mch_billno", no);
        map.put("mch_id", paySetting.getPayNo());
        map.put("wxappid", paySetting.getAppId());
        //map.put("nick_name", redPacket.getProvideName());
        map.put("send_name", shName);
        map.put("re_openid", openId);
        map.put("total_amount", StringNumber.format(StringNumber.mul(money, "100"),0));
        //map.put("min_value", StringNumber.mul(redPacket.getMoney(), "100"));
        //map.put("max_value", StringNumber.mul(redPacket.getMoney(), "100"));
        map.put("total_num", 1+"");
        map.put("wishing", sentiment);
        map.put("client_ip", ip);
        map.put("act_name", eventName);
        map.put("remark", remark);
        map.put("nonce_str", UUIDFactory.random());
        map.put("sign", SignUtil.wxZfSign(map, paySetting.getPayKey()));
        System.out.println("Key"+paySetting.getPayKey());
        System.out.println(map);
        return map;
    }

    private static String createRespXml(Map<String, String> respMap) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = respMap.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            String v = (String)entry.getValue();
            sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");
        }
        sb.append("</xml>");
        return sb.toString();
    }

    //发送红包
    public static Map<String, String> sendExecute(String respXml, String mch_id, String filePath) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException, DocumentException {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File(filePath)); //此处为证书所放的绝对路径
        try {
            keyStore.load(instream, mch_id.toCharArray());
        } finally {
            instream.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

        Map<String, String> map = new HashMap<String, String>();
        try {
            HttpPost httpPost = new HttpPost(send_redPacket_url);

            StringEntity reqEntity = new StringEntity(respXml, "utf-8");

            // 设置类型
            reqEntity.setContentType("application/x-www-form-urlencoded");

            httpPost.setEntity(reqEntity);

            System.out.println("executing request" + httpPost.getRequestLine());
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                System.out.println(response.getStatusLine());
                if (entity != null) {
                    // 从request中取得输入流
                    InputStream inputStream = entity.getContent();
                    // 读取输入流
                    SAXReader reader = new SAXReader();
                    Document document = reader.read(inputStream);
                    // 得到xml根元素
                    Element root = document.getRootElement();
                    // 得到根元素的所有子节点
                    List<Element> elementList = root.elements();
                    // 遍历所有子节点
                    for (Element e : elementList) {
                        map.put(e.getName(), e.getText());
                    }
                    // 释放资源
                    inputStream.close();
                    inputStream = null;
                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        return map;
    }

    //处理返回信息
    private static Map dealWithBackData(Map<String, String> map) throws Exception {
        String return_code = map.get("return_code"); // 返回状态码
        String return_msg = map.get("return_msg");//返回信息
        String result_code = map.get("result_code");  // 业务结果
        String err_code = map.get("err_code"); // 错误代码
        String err_code_des = map.get("err_code_des"); // 错误代码描述

        Map result = new HashMap();
        result.put("suc",false);
        result.put("msg",return_msg);
        if("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {
            result.put("suc",true);
            result.put("msg","");
        }
        return result;
    }
}
